/**
 * @Author: wzx
 * @Description:
 * @Version: 1.0.0
 * @Date: 2021/5/17 下午6:31
 *@Copyright: MIN-Group；国家重大科技基础设施——未来网络北大实验室；深圳市信息论与未来网络重点实验室
 */
package config

import (
	"bytes"
	"encoding/json"
	"fmt"
	"gopkg.in/ini.v1"
	"log"
	"os"
	"strings"
)

var Cfg *VPNConfig

type SessionConfig struct {
	DefaultExpiration int    `ini:"DefaultExpiration"`
	CleanupInterval   int    `ini:"CleanupInterval"`
	CachePath         string `ini:"CachePath"`
}

type KeyConfig struct {
	DefaultExpiration int    `ini:"DefaultExpiration"`
	CleanupInterval   int    `ini:"CleanupInterval"`
	CachePath         string `ini:"CachePath"`
}

type MysqlConfig struct {
	Name     string `ini:"Name"`
	Password string `ini:"Password"`
	IP       string `ini:"IP"`
	Port     string `ini:"Port"`
}

type RedisConfig struct {
	IP   string `ini:"IP"`
	Port string `ini:"Port"`
}

type FrontEndConfig struct {
	IP   string `ini:"IP"`
	Port string `ini:"Port"`
}

type FESSLConfig struct {
	IP     string `ini:"IP"`
	Port   string `ini:"Port"`
	Pubkey string `ini:"Pubkey"`
	Prikey string `ini:"Prikey"`
}

func (a FrontEndConfig) GetFEAddress() string {
	return a.IP + ":" + a.Port
}

func (ssl FESSLConfig) GetFESSLAddress() string {
	return ssl.IP + ":" + ssl.Port
}

type BlockChainConfig struct {
	IP   string `ini:"IP"`
	Port string `ini:"Port"`
}

type BCSSLConfig struct {
	IP     string `ini:"IP"`
	Port   string `ini:"Port"`
	Pubkey string `ini:"Pubkey"`
	Prikey string `ini:"Prikey"`
}

func (ssl BlockChainConfig) GetBCAddress() string {
	return ssl.IP + ":" + ssl.Port
}

func (ssl BCSSLConfig) GetBCSSLAddress() string {
	return ssl.IP + ":" + ssl.Port
}

type LogConfig struct {
	LogPath string `ini:"LogPath"`
	Level   int    `ini:"Level"`
}

type LogPoolConfig struct {
	NPoolSize int `ini:"NPoolSize"`
	WPoolSize int `ini:"WPoolSize"`
}

type MinSDKConfig struct {
	MinAppid string `ini:"MinAppid"`
}

type VPNConfig struct {
	LogConfig        `json:"Log" ini:"Log"`
	FrontEndConfig   `json:"FrontEnd" ini:"FrontEnd"`
	FESSLConfig      `json:"FE-SSL" ini:"FE-SSL"`
	BlockChainConfig `json:"BlockChain" ini:"BlockChain"`
	BCSSLConfig      `json:"BC-SSL" ini:"BC-SSL"`
	MysqlConfig      `json:"MYSQL" ini:"MYSQL"`
	RedisConfig      `json:"REDIS" ini:"REDIS"`
	SessionConfig    `json:"SESSION" ini:"SESSION"`
	KeyConfig        `json:"Key" ini:"Key"`
	LogPoolConfig    `json:"LogPool" ini:"LogPool"`
	MinSDKConfig     `json:"MinSDK" ini:"MinSDK"`
}

func ParseConfig(path string, show bool) *VPNConfig {
	cfg, err := ini.Load(path)
	if err != nil {
		log.Fatal("Fail to read ini file:", err)
	}
	vpnConfig := new(VPNConfig)
	// 直接使用反射 映射
	err = cfg.MapTo(vpnConfig)
	if err != nil {
		log.Fatal("Please check the config file,err:", err)
	}
	if show {
		vpnConfig.show()
	}
	return vpnConfig
}

func (config *VPNConfig) show() {
	var start = "---------------------------------------------------config----------------------------------------------"
	var mid = config.string()
	var end = "-------------------------------------------------------------------------------------------------------"
	fmt.Fprintln(os.Stdout, strings.Join([]string{"\033[1;32;48m", start, mid, end, "\033[0m"}, "\n"))
}

func (conf *VPNConfig) string() string {
	b, err := json.Marshal(*conf)
	if err != nil {
		return fmt.Sprintf("%+v", *conf)
	}
	var out bytes.Buffer
	err = json.Indent(&out, b, "", "    ")
	if err != nil {
		return fmt.Sprintf("%+v", *conf)
	}
	return out.String()
}
